home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / tape / tape.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-10  |  9.5 KB  |  323 lines

  1. /*
  2.  * tape.c --
  3.  *    Manipulate a tape drive.
  4.  */
  5. #include "sprite.h"
  6. #include "status.h"
  7. #include "time.h"
  8. #include "sys/file.h"
  9. #include "fs.h"
  10. #include "dev/tape.h"
  11. #include <dev/scsi.h>
  12. #include <sys/scsi.h>
  13. #include "stdio.h"
  14. #include "option.h"
  15. #include "errno.h"
  16. #include "tape.h"
  17.  
  18. char *tapeFile = "/dev/tape0";
  19. Boolean rewindIt = FALSE;
  20. Boolean retension = FALSE;
  21. Boolean gotoEnd = FALSE;
  22. Boolean readIt = FALSE;
  23. Boolean erase = FALSE;
  24. int skipFiles = 0;
  25. int skipBlocks = 0;
  26. int writeIt = 0;
  27. int blockSize = 16 * 1024;
  28. int weof = 0;
  29. int gotoBlock = -1;
  30. Boolean doStatus = FALSE;
  31. Boolean load = FALSE;
  32. Boolean unload = FALSE;
  33. Boolean prevent = FALSE;
  34. Boolean allow = FALSE;
  35. Boolean inquiry = FALSE;
  36.  
  37. Option optionArray[] = {
  38.     { OPT_STRING, "t", (Address)&tapeFile, "Name of tape device" },
  39.     { OPT_TRUE, "r", (Address)&rewindIt, "Rewind the tape" },
  40.     { OPT_TRUE, "T", (Address)&retension, "Retension the tape" },
  41.     { OPT_TRUE, "e", (Address)&gotoEnd, "Skip to the end of data." },
  42.     { OPT_INT, "f", (Address)&skipFiles, "Number of tape files to skip" }, 
  43.     { OPT_INT, "b", (Address)&skipBlocks, "Number of blocks to skip" }, 
  44.     { OPT_INT, "m", (Address)&weof, "Number of end-of-file marks to write" }, 
  45.     { OPT_INT, "B", (Address)&blockSize, "Block size" },
  46.     { OPT_TRUE, "R", (Address)&readIt, "Read til end of file"},
  47.     { OPT_INT, "W",  (Address)&writeIt, "Write -W N blocks"},
  48.     { OPT_TRUE, "E",  (Address)&erase, "Erase the whole tape!"},
  49.     { OPT_INT, "g", (Address) &gotoBlock, "Goto block N"},
  50.     { OPT_TRUE, "s", (Address) &doStatus, "Print tape status"},
  51.     { OPT_TRUE, "l", (Address) &load, "Load tape"},
  52.     { OPT_TRUE, "u", (Address) &unload, "Unload tape"},
  53.     { OPT_TRUE, "p", (Address) &prevent, "Prevent tape removal"},
  54.     { OPT_TRUE, "a", (Address) &allow, "Allow tape removal"},
  55.     { OPT_TRUE, "i", (Address) &inquiry, "Perform tape inquiry"}
  56. };
  57. int numOptions = sizeof(optionArray) / sizeof(Option);
  58.  
  59. main(argc, argv)
  60. int argc;
  61. char **argv;
  62. {
  63.     int oldOffset;
  64.     ReturnStatus status;
  65.     int tapeStream;
  66.     Address buffer;
  67.     int amountRead, amountWritten, total;
  68.     int openFlags;
  69.  
  70.     argc = Opt_Parse(argc, argv, optionArray, numOptions, 0);
  71.  
  72.     if (writeIt || weof) {
  73.     openFlags = O_RDWR;
  74.     } else {
  75.     openFlags = O_RDONLY;
  76.     }
  77.     tapeStream = open(tapeFile, openFlags, 0);
  78.     if (tapeStream < 0) {
  79.     perror("Can't open tape drive");
  80.     exit(errno);
  81.     }
  82.     buffer = (Address)malloc(blockSize);
  83.     if (inquiry) {
  84.     status = Inquiry(tapeStream);
  85.     if (status != SUCCESS) {
  86.         Stat_PrintMsg(status, "Can't perform inquiry");
  87.         exit(status);
  88.     }
  89.     }
  90.  
  91.     if (retension) {
  92.     status = Ioc_TapeCommand(tapeStream, IOC_TAPE_RETENSION, 1);
  93.     if (status != SUCCESS) {
  94.         Stat_PrintMsg(status, "Can't retension tape");
  95.         exit(status);
  96.     }
  97.     }
  98.  
  99.     if (gotoEnd) {
  100.     status = Ioc_TapeCommand(tapeStream, IOC_TAPE_SKIP_EOD, 0);
  101.     if (status != SUCCESS) {
  102.         Stat_PrintMsg(status, "Can't position at end-of-tape");
  103.         exit(status);
  104.     }
  105.     }
  106.     if (rewindIt) {
  107.     status = Ioc_Reposition(tapeStream, IOC_BASE_ZERO, 0, &oldOffset);
  108.     if (status != SUCCESS) {
  109.         Stat_PrintMsg(status, "Can't rewind tape drive");
  110.         exit(status);
  111.     }
  112.     }
  113.     if (erase) {
  114.     char answer[40];
  115.     printf("Really erase the tape? ");
  116.     scanf(" %s", answer);
  117.     if (answer[0] == 'y' || answer[0] == 'Y') {
  118.         printf("Ok, here goes\n");
  119.         status = Ioc_TapeCommand(tapeStream, IOC_TAPE_ERASE, 0);
  120.         if (status != SUCCESS) {
  121.         Stat_PrintMsg(status, "Can't erase tape");
  122.         exit(status);
  123.         }
  124.     } else {
  125.         printf("Ok, not erasing\n");
  126.     }
  127.     }
  128.     if (skipFiles) {
  129.     status = Ioc_TapeCommand(tapeStream, IOC_TAPE_SKIP_FILES, skipFiles);
  130.     if (status != SUCCESS) {
  131.         Stat_PrintMsg(status, "Can't skip tape files");
  132.         exit(status);
  133.     }
  134.     } else if (skipBlocks > 0) {
  135.     status = Ioc_TapeCommand(tapeStream, IOC_TAPE_SKIP_BLOCKS, skipBlocks);
  136.     if (status != SUCCESS) {
  137.         Stat_PrintMsg(status, "Can't skip tape blocks");
  138.         exit(status);
  139.     }
  140.     }
  141.     if (weof) {
  142.     status = Ioc_TapeCommand(tapeStream, IOC_TAPE_WEOF, weof);
  143.     if (status != SUCCESS) {
  144.         Stat_PrintMsg(status, "Can't write file mark(s)");
  145.         exit(status);
  146.     }
  147.     }
  148.  
  149.     if (writeIt > 0) {
  150.     total = 0;
  151.     while (writeIt-- > 0) {
  152.         amountWritten = write(tapeStream, buffer, blockSize);
  153.         if (amountWritten < 0) {
  154.         break;
  155.         }
  156.         total += amountWritten;
  157.         if (amountWritten < blockSize) {
  158.         break;
  159.         }
  160.     }
  161.     fprintf(stderr, "Wrote %d bytes\n", total);
  162.     if (amountWritten < 0) {
  163.         perror("Tape write failed");
  164.     }
  165.     } else if (readIt) {
  166.     total = 0;
  167.     while (1) {
  168.         amountRead = read(tapeStream, buffer, blockSize, buffer);
  169.         if (amountRead <= 0) {
  170.         break;
  171.         }
  172.         total += amountRead;
  173.     }
  174.     if (amountRead < 0) {
  175.         perror("Tape read failed");
  176.     }
  177.     fprintf(stderr, "Read %d bytes\n", total);
  178.     }
  179.     if (gotoBlock != -1) {
  180.         status = Ioc_TapeCommand(tapeStream, IOC_TAPE_GOTO_BLOCK, gotoBlock);
  181.     if (status != SUCCESS) {
  182.         Stat_PrintMsg(status, "Can't goto block");
  183.         exit(status);
  184.     }
  185.     }
  186.     if (doStatus) {
  187.     Dev_TapeStatus    tapeStatus;
  188.     bzero((char *) &tapeStatus, sizeof(tapeStatus));
  189.     status = Fs_IOControl(tapeStream, IOC_TAPE_STATUS, 0, NULL, 
  190.         sizeof(tapeStatus), &tapeStatus);
  191.     if (status != SUCCESS) {
  192.         Stat_PrintMsg(status, "Can't get status");
  193.         exit(status);
  194.     }
  195.     printf("Type : 0x%x\n", tapeStatus.type);
  196.     printf("Serial : %s\n", tapeStatus.serial);
  197.     printf("Block size : %d\n", tapeStatus.blockSize);
  198.     printf("Current block : %d\n", tapeStatus.position);
  199.     printf("Remaining blocks : %d\n", tapeStatus.remaining);
  200.     printf("Data errors : %d\n", tapeStatus.dataError);
  201.     printf("Read/Write retry : %d\n", tapeStatus.readWriteRetry);
  202.     printf("Tracking retry : %d\n", tapeStatus.trackingRetry);
  203.     printf("Write protect : %d\n", tapeStatus.writeProtect);
  204.     printf("Buffered mode : %d\n", tapeStatus.bufferedMode);
  205.     printf("Speed : %d\n", tapeStatus.speed);
  206.     printf("Density : %d\n", tapeStatus.density);
  207.     }
  208.     if (load) {
  209.     status = Ioc_TapeCommand(tapeStream, IOC_TAPE_LOAD, 0);
  210.     if (status != SUCCESS) {
  211.         Stat_PrintMsg(status, "Can't load tape");
  212.         exit(status);
  213.     }
  214.     }
  215.     if (unload) {
  216.     status = Ioc_TapeCommand(tapeStream, IOC_TAPE_UNLOAD, 0);
  217.     if (status != SUCCESS) {
  218.         Stat_PrintMsg(status, "Can't unload tape");
  219.         exit(status);
  220.     }
  221.     }
  222.     if (prevent) {
  223.     status = Ioc_TapeCommand(tapeStream, IOC_TAPE_PREVENT_REMOVAL, 0);
  224.     if (status != SUCCESS) {
  225.         Stat_PrintMsg(status, "Can't prevent tape removal");
  226.         exit(status);
  227.     }
  228.     }
  229.     if (allow) {
  230.     status = Ioc_TapeCommand(tapeStream, IOC_TAPE_ALLOW_REMOVAL, 0);
  231.     if (status != SUCCESS) {
  232.         Stat_PrintMsg(status, "Can't allow tape removal");
  233.         exit(status);
  234.     }
  235.     }
  236.     close(tapeStream);
  237.     fprintf(stderr, "done\n");
  238.     exit(SUCCESS);
  239. }
  240.  
  241. static int
  242. Inquiry(fd)
  243. int fd;
  244. {
  245.     int status;
  246.     char buf[80];
  247.  
  248.     struct InCmd {
  249.     Dev_ScsiCommand hdr;
  250.     InquiryCommand cmd;    
  251.     } inCmd; 
  252.  
  253.     struct OutStatus {
  254.     Dev_ScsiStatus hdr;
  255.     struct InquiryData {
  256. #if BYTE_ORDER == BIG_ENDIAN
  257.         unsigned char type;         /* Peripheral device type */
  258.         unsigned char rmb:1;        /* Removable Medium bit. */
  259.         unsigned char qualifier:7;  /* Device type qualifier. */
  260.         unsigned char version;      /* Version info. */
  261.         unsigned char reserved:4;   /* reserved. */
  262.         unsigned char format:4;     /* Response format. */
  263. #else /* BYTE_ORDER == LITTLE_ENDIAN */
  264.         unsigned char type;        /* Peripheral device type. */
  265.         unsigned char qualifier:7;    /* Device Type qualifier. */
  266.         unsigned char rmb:1;    /* Removable Medium bit. */
  267.         unsigned char version;    /* Version info. */
  268.         unsigned char format:4;    /* Response format */
  269.         unsigned char reserved:4;    /* reserved. */
  270. #endif
  271.         unsigned char length;         /* Additional length of data returned. */
  272.         unsigned char reserved2[3];   /* More reserved and not supported. */
  273.         char          vendorID[8];  /* Vector identification. */
  274.         char          productID[16]; /* Product identification. */
  275.         char          revLevel[4]; /* Firmware identification. */
  276.         unsigned char reserved3[20];  /* More reserved. */
  277.     } inquiryData; 
  278.     } outStatus;
  279.  
  280.     memset(&inCmd, 0, sizeof(inCmd));
  281.     memset(&outStatus, 0, sizeof(outStatus));
  282.     
  283.     inCmd.hdr.bufferLen = sizeof(struct InquiryData);
  284.     inCmd.hdr.commandLen = sizeof(InquiryCommand);
  285.     inCmd.hdr.dataOffset = sizeof(Dev_ScsiCommand) + sizeof(InquiryCommand);
  286.  
  287. /* Fill in Command Descriptor Block. */
  288.  
  289.     inCmd.cmd.command = SCSI_INQUIRY;
  290.     inCmd.cmd.unitNumber = 0;    /* For our purposes, the unitNumber is always
  291.                  * zero. 
  292.                  */
  293.     inCmd.cmd.evpd = 0;        /* The EXB-120 only supports 0 for this field. */
  294.     inCmd.cmd.allocLength = 0x38;
  295.     inCmd.cmd.link = 0;
  296.     inCmd.cmd.flag = 0;
  297.     inCmd.cmd.vendorUnique = 0;
  298.     
  299.     status = Fs_IOControl(fd, IOC_SCSI_COMMAND,
  300.               inCmd.hdr.dataOffset, (void *) &inCmd,
  301.               sizeof(outStatus), (void *) &outStatus);
  302.  
  303.     printf("Scsi status byte = 0x%x\n", outStatus.hdr.statusByte);
  304.     printf("Scsi transfer len = %d\n", outStatus.hdr.amountTransferred);
  305.     printf("Scsi senseData len = %d\n", outStatus.hdr.senseDataLen);
  306.  
  307.     strncpy(buf,outStatus.inquiryData.vendorID,
  308.         sizeof(outStatus.inquiryData.vendorID));
  309.     *(buf+sizeof(outStatus.inquiryData.vendorID)) = '\0';
  310.     printf("Vendor ID = %s\n", buf);
  311.     strncpy(buf,outStatus.inquiryData.productID,
  312.         sizeof(outStatus.inquiryData.productID));
  313.     *(buf+sizeof(outStatus.inquiryData.productID)) = '\0';
  314.     printf("Product ID = %s\n", buf);
  315.     strncpy(buf,outStatus.inquiryData.revLevel,
  316.         sizeof(outStatus.inquiryData.revLevel));
  317.     *(buf+sizeof(outStatus.inquiryData.revLevel)) = '\0';
  318.     printf("Rev level = %s\n", buf);
  319.  
  320.     return status;
  321. }
  322.  
  323.